package com.xyzwps.lib.express.router.ap;

import com.google.auto.service.AutoService;
import com.xyzwps.lib.ap.Accessors;
import com.xyzwps.lib.ap.JavaFileWriter;
import com.xyzwps.lib.ap.TypeInfo;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import java.util.Set;

import static com.xyzwps.lib.dollar.Dollar.*;

@AutoService(Processor.class)
@SupportedAnnotationTypes("com.xyzwps.lib.express.router.annotation.openapi.SchemaComponent")
public class OpenApiSchemaAP extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        try {
            for (TypeElement annotation : annotations) {
                for (var element : roundEnv.getElementsAnnotatedWith(annotation)) {
                    if (element instanceof TypeElement typeElement) {
                        System.out.println("🚩SchemaComponentAP Found class: " + typeElement);
                        var typeInfo = TypeInfo.of(typeElement);
                        var accessors = Accessors.fromTypeInfo(typeInfo);
                        if (accessors.isNotEmpty()) {
                            generateOpenApiSchemaCustomizer(typeInfo, accessors);
                        }
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("🚩SchemaComponentAP Error: " + e.getMessage());
            e.printStackTrace(System.out);
            throw e;
        }
        return true;
    }

    private void generateOpenApiSchemaCustomizer(TypeInfo typeInfo, Accessors accessors) {
        var generatedClassName = "OpenApiSchemaCustomizerFor_" + typeInfo.canonicalName().replaceAll("\\.", "_") + "$AP";
        var lines = new Lines();
        lines.add("package " + typeInfo.packageName() + ";");
        lines.add("");
        lines.add("import com.xyzwps.lib.openapi.element.OpenApiCustomizer;");
        lines.add("import com.xyzwps.lib.openapi.element.OpenApi;");
        lines.add("import com.xyzwps.lib.openapi.element.Schema;");
        lines.add("import jakarta.inject.Singleton;");
        lines.add("");
        lines.add("@Singleton");
        lines.add("public class " + generatedClassName + " implements OpenApiCustomizer {");

        lines.indentPP();
        // region customizer
        lines.add("@Override");
        lines.add("public void accept(OpenApi it) {");
        lines.indentPP();

        lines.add("var s = new Schema.ObjectSchema();");
        for (var accessor : accessors.accessors()) {
            lines.add("s.addProperty(\"" + $.unescape(accessor.name()) + "\", new Schema.StringSchema());");  // TODO: 处理类型
        }
        lines.add("it.components().addSchema(\"" + $.unescape(typeInfo.canonicalName()) + "\", s);");

        lines.indentMM();
        lines.add("}");
        // endregion
        lines.indentMM();

        lines.add("}");

        JavaFileWriter.write(typeInfo.packageName() + "." + generatedClassName, lines.toString(), processingEnv);
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.RELEASE_21;
    }
}
